package com.orzxlee.InterviewQuestions.Java_SE_Base;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 华为面试题:
 *      为什么函数不能根据返回类型来区分重载？
 *
 *      方法名,参数列表相同,不能用返回值来区分
 *
 */
public class Inter {

   public  float max(float a, float b){

       return a+b;
   }

   //1. 方法重载,当方法名,方法参数相同时
//   public int max(float a, float b){
//
//           return (int) (a+b);
//   }

    public static void main(String[] args) {

        //1.throw throws 异常关键字
        //fun()
        //2.String 类 引用内存地址比较
        //fun2();
        //3.日期
        //fun3();
        //4.String类length()方法,数组length属性
        //fun4();
        //5.方法重载,不能用返回值类型区分
        //fun5();
        //6.String 、StringBuilder 、StringBuffer
        //fun6();
        //7.日期
        //fun7();
        //8.日期
        //fun8();
        //9.日期
        //fun9();
        //10.日期
        //fun10();
        //11.日期
        //fun11();
        //12.隐式类型转换
        //fun12();

        //13.int 和 和 Integer 有什么区别
        //如果整型字面量的值在-128 到 127 之间，那么不会 new 新的 Integer 对象，而是直接引用常量池
        //中的 Integer 对象，所以上面的面试题中 f1==f2 的结果是 true，而 f3==f4 的结果是 false
        //fun13();

        //14. 集合 要求对 HashMap 中的 User 的 age 倒序进行排序。排序时 key=value 键值对不得拆散
        //fun14();

        //15. 集合线程安全 问 ArrayList、HashSet、HashMap 是线程安全的吗？如果不是我想要线程安全的集合怎么办?
        //fun15();

        //16. 并发集合
        //fun16();

        //17.List 接口的三个子类的特点 ArrayList  LinkedList vector ? List 和 Map、Set 的区别 ?
        //fun17();

        //18.多线程
        //1.在 java 中 wait 和 sleep 方法的不同？
        //最大的不同是在等待时 wait 会释放锁，而 sleep 一直持有锁。wait 通常被用于线程间交互，sleep 通常被用于暂停执行
        //2.synchronized 和 volatile 关键字的作用
        /*
            volatile 本质是在告诉 jvm 当前变量在寄存器（工作内存）中的值是不确定的，需要从主存中读取；
            synchronized 则是锁定当前变量，只有当前线程可以访问该变量，其他线程被阻塞住。
            1.volatile 仅能使用在变量级别；
                synchronized 则可以使用在变量、方法、和类级别的
            2.volatile 仅能实现变量的修改可见性，并不能保证原子性；
                synchronized 则可以保证变量的修改可见性和原子性
            3.volatile 不会造成线程的阻塞；
                synchronized 可能会造成线程的阻塞。
            4.volatile 标记的变量不会被编译器优化；
                synchronized 标记的变量可以被编译器优化
         */

        //3.线程和进程的区别?
        //进程：具有一定独立功能的程序关于某个数据集合上的一次运行活动，是操作系统进行资源分配和调度的一个独立单位
        //线程：是进程的一个实体，是 cpu 调度和分派的基本单位，是比进程更小的可以独立运行的基本单位

        //4.请说出同步线程及线程调度相关的方法？
        /*
            wait()：使一个线程处于等待（阻塞）状态，并且释放所持有的对象的锁；
            sleep()：使一个正在运行的线程处于睡眠状态，是一个静态方法，调用此方法要处理 InterruptedException 异常；
            notify()：唤醒一个处于等待状态的线程，当然在调用此方法的时候，并不能确切的唤醒某一个等待状态的线程而是由 JVM 确定唤醒哪个线程，而且与优先级无关；
            notifyAll()：唤醒所有处于等待状态的线程，该方法并不是将对象的锁给所有线程，而是让它们竞争，只有获得锁的线程才能进入就绪状态；
         */

        //5.启动一个线程是调用 run()方法还是 start()方法？
        //start() 启动线程
        //run() 回调函数





    }

    private static void fun17() {
        // List 单列数据,有序,允许重复
        // set 单列数据,无序,不重复 ,元素的位置由 hashcode 决定,位置固定
        // Map 键值对(双列数据),无序,Key不能重复,Value可以重复


        // List 接口三个实现类
        // LinkedList基于链表实现,底层链表,查询慢,增删快。
        // ArrayList基于数组实现,底层数组,查询快,增删慢
        // Vector基于数组实现, 底层数组 查询快,增删慢,线程安全
        // Map 接口三个实现类
        //HashMap 基于hash表的Map接口实现,非线程安全,高效,支持 null 值和 null键
        //HashTable  线程安全,低效,不支持 null 值和 null 键
        //LinkedHashMap 是 HashMap 的一个子类 记录的插入顺序,通过SortMap 接口：TreeMap的记录根据键排序,默认是键值的升序排序

        //Collection 和 Map 的集成体系
        //Queue 队列 接口
        //1.PriorityQueue 类
        //2.Deque 接口
        //ArrayDeque 类
        //List 接口 有序,重复
        //1.ArrayList;
        //2.LinkedList;
        //3.Vector;
        //Stack
        //Set 接口 无序,不重复
        //1.EnumSet 类
        //2.SortedSet 接口
        //TreeSet
        //3.HashSet 类
        //LinkedHashSet

        //Map 接口
        //HashMap;
        //LinkedHashMap;
        //SortedMap 接口
        //TreeMap 类
    }

    private static void fun16() {
        //是线程安全的 HashMap 的实现
        ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap();
        //基于链表的无界线程安全队列
        ConcurrentLinkedQueue concurrentLinkedQueue = new ConcurrentLinkedQueue();
        //是基于链表的无限双端队列，线程安全
        ConcurrentLinkedDeque concurrentLinkedDeque = new ConcurrentLinkedDeque();
    }

    private static void fun15() {
        Collection c = new ArrayList();
        ArrayList arrayList = new ArrayList();
        Map map = new HashMap();
        Set set = new HashSet();

        //转换为线程安全的集合
        Collection collection = Collections.synchronizedCollection(c);
        List list = Collections.synchronizedList(arrayList);
        Map map1 = Collections.synchronizedMap(map);
        Set set1 = Collections.synchronizedSet(set);
    }

    private static void fun14() {
        HashMap<Integer, User> users = new HashMap<>();
        users.put(1, new User("张三", 25));
        users.put(3, new User("李四", 22));
        users.put(2, new User("王五", 28));
        System.out.println(users);
        HashMap<Integer,User> sortHashMap = sortHashMap(users);
        System.out.println(sortHashMap);
    }

    private static HashMap<Integer, User> sortHashMap(HashMap<Integer, User> map) {
        // 首先拿到 map 的键值对集合
        Set<Map.Entry<Integer, User>> entrySet = map.entrySet();

        // 将 set 集合转为 List 集合，为什么，为了使用工具类的排序方法
        List<Map.Entry<Integer, User>> list = new ArrayList<Map.Entry<Integer, User>>(entrySet);
        // 使用 Collections 集合工具类对 list 进行排序，排序规则使用匿名内部类来实现
        /*Collections.sort(list, new Comparator<Map.Entry<Integer, User>>() {

            @Override
            public int compare(Map.Entry<Integer, User> o1, Map.Entry<Integer, User> o2) {
                //按照要求根据 User 的 age 的倒序进行排
                return o2.getValue().getAge() - o1.getValue().getAge();
            }
        });*/

        // Lambda表达式实现  按照age 升序排序
        //Collections.sort(list,(o1, o2) -> o1.getValue().getAge() - o2.getValue().getAge());

        // Lambda表达式实现  按照age 降序排序
        Collections.sort(list,(o1, o2) -> o2.getValue().getAge() - o1.getValue().getAge());

        //创建一个新的有序的 HashMap 子类的集合
        LinkedHashMap<Integer, User> linkedHashMap = new LinkedHashMap<Integer, User>();
        //将 List 中的数据存储在 LinkedHashMap 中
        for (Map.Entry<Integer, User> entry : list) {
            linkedHashMap.put(entry.getKey(), entry.getValue());

        }
        return linkedHashMap;
    }

    private static void fun13() {
       // == 比较的是引用内存地址值
        Integer f1 = 100, f2 = 100, f3 = 150 ,f4 = 150;
        System.out.println(f1 == f2);//true  //直接引用常量池对象
        System.out.println(f3 == f4);//false //返回新对象
    }

    private static void fun12() {
       //short s1 = 1; s1 = s1 + 1; 有错吗?short s1 = 1; s1 += 1 有错吗
        short s1 = 1;
        s1  = (short) (s1 +1);

        short s2 = 2;
        //其中有隐含的强制类型转换
        s2 +=2;
    }

    private static void fun11() {
        //Current Time
        LocalTime time = LocalTime.now();
        //HH-mm-ss
        System.out.println("Current Time="+time);
        //Creating LocalTime by providing input arguments
        //nanoOfSecond 纳秒
        LocalTime specificTime = LocalTime.of(12,20,25,40);
        System.out.println("Specific Time of Day="+specificTime);
        //Try creating time by providing invalid inputs
        //LocalTime invalidTime = LocalTime.of(25,20);
        //Exception in thread "main" java.time.DateTimeException:
        //Invalid value for HourOfDay (valid values 0 - 23): 25
        //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc
        LocalTime timeKolkata = LocalTime.now(ZoneId.of("Asia/Kolkata"));
        System.out.println("Current Time in IST="+timeKolkata);
        //java.time.zone.ZoneRulesException: Unknown time-zone ID: IST
        //LocalTime todayIST = LocalTime.now(ZoneId.of("IST"));
        //Getting date from the base date i.e 01/01/1970
        // 1秒
        LocalTime specificSecondTime = LocalTime.ofSecondOfDay(1);
        System.out.println("10000th second time= "+specificSecondTime);
    }

    private static void fun10() {
        //Current Date
        LocalDate today = LocalDate.now();
        System.out.println("Current Date="+today);
        //Creating LocalDate by providing input arguments
        LocalDate firstDay_2014 = LocalDate.of(2014, Month.JANUARY, 1);
        System.out.println("Specific Date="+firstDay_2014);
        //Try creating date by providing invalid inputs
        //LocalDate feb29_2014 = LocalDate.of(2014, Month.FEBRUARY, 29);
        //Exception in thread "main" java.time.DateTimeException:
        //Invalid date 'February 29' as '2014' is not a leap year
        //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc
        LocalDate todayShanghai = LocalDate.now(ZoneId.of("Asia/Shanghai"));
        System.out.println("Current Date in IST Shanghai="+todayShanghai);
        //java.time.zone.ZoneRulesException: Unknown time-zone ID: IST
        //LocalDate todayIST = LocalDate.now(ZoneId.of("IST"));
        //Getting date from the base date i.e 01/01/1970
        //在1970-01-01 追加日期
        LocalDate dateFromBase = LocalDate.ofEpochDay(365);
        System.out.println("365th day from base date= "+dateFromBase);
        //2021 年的 第33天
        LocalDate oneDay2021 = LocalDate.ofYearDay(2022, 33);
        System.out.println("33th day of 2021="+oneDay2021);
    }

    private static void fun9() {
        //打印昨天的当前时刻
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1);
        System.out.println(cal.getTime());

        //java 8
        LocalDateTime today = LocalDateTime.now();
        LocalDateTime yesterday = today.minusDays(1);
        System.out.println(yesterday);
    }

    private static void fun8() {
        //获取当前月第一天：
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH,1);//设置为 1 号,当前日期既为本月第一天
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String first = format.format(c.getTime());
        System.out.println("本月第一天:"+first);

        //获取当前月最后一天
        Calendar ca = Calendar.getInstance();
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        String last = format.format(ca.getTime());
        System.out.println("本月最后一天:"+last);

        //Java 8
        LocalDate today = LocalDate.now();
        //本月的第一天
        LocalDate firstDay = LocalDate.of(today.getYear(),today.getMonth(),1);
        //本月的最后一天
        LocalDate lastDay =today.with(TemporalAdjusters.lastDayOfMonth());
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formatFirstDay = dateTimeFormatter.format(firstDay);
        String formatLastDay = dateTimeFormatter.format(lastDay);

        System.out.println("Java8 本月的第一天:"+formatFirstDay);
        System.out.println("Java8 本月的最后一天:"+formatLastDay);
    }

    private static void fun7() {
        //如何取得从 1970 年 1 月 1 日 0 时 0 分 0 秒到现在的毫秒数
        Calendar.getInstance().getTimeInMillis(); //第一种方式
        System.currentTimeMillis(); //第二种方式
        // Java 8
        Clock.systemDefaultZone().millis();
    }

    private static void fun6() {

       //buffer 缓冲器 ,线程安全

       /*
       （1）、可变不可变
            String：字符串常量，在修改时不会改变自身；若修改，等于重新生成新的字符串对象。
            StringBuffer：在修改时会改变对象自身，每次操作都是对 StringBuffer 对象本身进行修改，不是生成新的对
            象；使用场景：对字符串经常改变情况下，主要方法：append（），insert（）等。
            （2）、线程是否安全
            String：对象定义后不可变，线程安全。
            StringBuffer：是线程安全的（对调用方法加入同步锁），执行效率较慢，适用于多线程下操作字符串缓冲区
            大量数据。
            StringBuilder：是线程不安全的，适用于单线程下操作字符串缓冲区大量数据。
            （3）、共同点
            StringBuilder 与 StringBuffer 有公共父类 AbstractStringBuilder(抽象类)。
        */

        //5.String 、StringBuilder 、StringBuffer 的区别？
        //String 只读字符串  被final修饰过的类 ,s为引用对象,第一次指向"abc"对象 ,第二次指向了"qwe"对象
        String s = "abc";
        s = "qwe";

        //StringBuilder jdk5中引入的,所有方法未被synchronized修饰,效率更高
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.toString();

        //所有方法都被synchronized修饰  线程安全
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.toString();


        //String s3 = "abc";
        //String ss = "ok" + s3 + "xyz" + 5;
        //System.out.println(ss);
    }

    private static void fun5() {
        Inter inter = new Inter();
        float max = inter.max(2.1f, 2.2f);
        System.out.println(max);
    }

    private static void fun4() {
        //4.数组有没有 length() 方法？String 有没有 length() 方法
        String [] arr = {"a","c"};
        //数组中有length 属性
        int length = arr.length;

        //有length()方法 String是一个类,类中的方法
        String str = "ac";
        str.length();
    }

    private static void fun3() {
        //如何取得年月日、小时分钟秒
        Calendar cal = Calendar.getInstance();
        System.out.println(cal.get(Calendar.YEAR));
        System.out.println(cal.get(Calendar.MONTH)); // 0 - 11
        System.out.println(cal.get(Calendar.DATE));
        System.out.println(cal.get(Calendar.HOUR_OF_DAY));
        System.out.println(cal.get(Calendar.MINUTE));
        System.out.println(cal.get(Calendar.SECOND));
        // Java 8
        System.out.println("java 8 ----");
        LocalDateTime dt = LocalDateTime.now();
        System.out.println(dt.getYear());
        System.out.println(dt.getMonthValue()); // 1 - 12
        System.out.println(dt.getDayOfMonth());
        System.out.println(dt.getHour());
        System.out.println(dt.getMinute());
        System.out.println(dt.getSecond());
    }

    private static void fun2() {
        String s1 = "Programming";
        String s2 = new String("Programming");
        String s3 = "Program";
        String s4 = "ming";
        String s5 = "Program" + "ming";
        String s6 = s3 + s4;
        //获取内存地址
        System.out.println(System.identityHashCode(s1));//1163157884
        System.out.println(System.identityHashCode(s2));//1956725890
        System.out.println(System.identityHashCode(s3));//356573597
        System.out.println(System.identityHashCode(s4));//1735600054
        System.out.println(System.identityHashCode(s5));//1163157884
        System.out.println(System.identityHashCode(s6));//21685669
        System.out.println(System.identityHashCode(s6.intern())); //1163157884
        System.out.println(System.identityHashCode(s2.intern())); //1163157884

        System.out.println("----------");
        //== 比较的是内存地址    intern（）方法会得到字符串对象在常量池中对应的版本的引用
        System.out.println(s1 == s2); //false
        System.out.println(s1 == s5); //true
        System.out.println(s1 == s6); //false
        System.out.println(s1 == s6.intern()); //true
        System.out.println(s2 == s2.intern());//false
    }


    /*
         2.
         throw throws 异常区别 ,
         throw 在方法体中声明, 直接抛出,自己处理异常
         throws 在方法头中声明,往上抛出异常,异常抛给调用者
     */
   //
   public  void fun () throws RuntimeException{
       try {
                int i = 1/0;

       }catch(Exception e){

           //在方法体中抛出异常
           throw  new RuntimeException();
       }

   }

   /*
        3.
          final :用于声明,成员,方法,类
          finally:异常处理关键字,表示总执行
          finalize:Object类的一个方法 protected void finalize() throws Throwable { }

    */

}
